package com.cloudinnov.websocket;

import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.cloudinnov.utils.CommonUtils;

@ServerEndpoint("/predictionAlarm")
public class PredictionAlarmWebsocket {
	private static Logger LOG = LoggerFactory.getLogger(PredictionAlarmWebsocket.class);
	public static final String SPLIT1 = ":";

	/*// 设备分类标识
	static final String JBZM = "JBZM";
	static final String JQZM = "JQZM";
	static final String YJZM = "YJZM";
	static final String FXKBQ = "FXKBQ";
	static final String SDFJ = "SDFJ";
	static final String CDZSQ = "CDZSQ";
	static final String HDJIM = "HDJIM";
	static final String JTXHD = "JTXHD";
	//json的key值
	static final String TITTLE = "tittle";
	static final String EQUIPMENTS = "equipments";
	static final String PREDICTIONNAME = "predictionName";
	static final String PREDICTIONEQUIPMENTS = "predictionEquipments";
	public static int digit = 5; //生成code的默认长度值
    */	
	
	private String random;
	private static int onlineCount = 0;
	// 用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话，可以使用Map来存放，其中Key可以为用户标识
	public static ConcurrentMap<String, PredictionAlarmWebsocket> webSocketMap = new ConcurrentHashMap<String, PredictionAlarmWebsocket>();
	// 用来发送数据
	private Session session;
	
	/*private PredictionRuleTableLogic predictionRuleTableLogic = SpringUtils.getBean("predictionRuleTableLogic");
	private EquipmentsLogic equipmentsLogic = SpringUtils.getBean("equipmentsLogic");
	private ControlSolutionLogic controlSolutionLogic = SpringUtils.getBean("controlSolutionLogic");
	*/
	
	@OnOpen
	public void onOpen(Session session) {
		this.session = session;
		this.random = CommonUtils.getUUID();
		webSocketMap.put(random, this);
		// 连接人数加1
		addOnlineCount();
		LOG.debug("预案警告推送开始连接:" + random);
	}

	@OnMessage
	public void onMessage(String message, Session session) throws Exception {
		/*LOG.debug("预案确定后,前端传值: " + message);
		
		Map<String, Object> prediction = new HashMap<>();
		if (message != null && JSON.parseObject(message, Equipments.class) instanceof Equipments) {
			Equipments messageEquip = JSON.parseObject(message, Equipments.class);
			
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			String predictionName = "";
			String alarmPosition = "";
			String alarmEquipName = "";
			String accidentArea = "";
			String accidentCameraCode = "";
			String alarmDate = sdf.format(new Date());
			//获取报警设备信息
			FireMQConsumer fireMQConsumer = new FireMQConsumer();
			Object arlarmEquipment = fireMQConsumer.getArlarmEquipment();
			if ("null".equals(arlarmEquipment.toString())) { 	//返回的结果为null,没有硬件触发预案
				alarmPosition = messageEquip.getPileNo();
				alarmEquipName = messageEquip.getEquipmentName();
				accidentArea = messageEquip.getAreaId();
				accidentCameraCode = messageEquip.getCode();
				
				//预案触发时返回前端的值
				prediction.put("alarmPosition", alarmPosition);
				prediction.put("alarmDate", alarmDate);
				prediction.put("accidentArea", accidentArea);
				prediction.put("alarmEquipName", alarmEquipName);
				prediction.put("accidentCameraCode", accidentCameraCode);
			}else { 	//返回的有设备,获取设备的报警信息
				Equipments arlarmEquip = (Equipments)arlarmEquipment;
				alarmPosition = arlarmEquip.getPileNo();
				alarmEquipName = arlarmEquip.getName();
				accidentArea = messageEquip.getAreaId();
				accidentCameraCode = messageEquip.getCode();
				
				//预案触发时返回前端的值
				prediction.put("alarmPosition", alarmPosition);
				prediction.put("alarmDate", alarmDate);
				prediction.put("accidentArea", accidentArea);
				prediction.put("alarmEquipName", alarmEquipName);
				prediction.put("accidentCameraCode", accidentCameraCode);
			}
			Map<String, Object> equipmentList1 = new HashMap<>();
			Map<String, Object> equipmentList2 = new HashMap<>();
			Map<String, Object> equipmentList3 = new HashMap<>();
			Map<String, Object> equipmentList4 = new HashMap<>();
			Map<String, Object> equipmentList5 = new HashMap<>();
		
			// 根据报警的位置动态获取预案
			PredictionRuleTable predictionRuleTable = new PredictionRuleTable();
			predictionRuleTable.setAccidentArea(messageEquip.getAreaId());
			predictionRuleTable.setSectionCode(messageEquip.getSectionCode());
			predictionRuleTable.setAccidentType(messageEquip.getAccidentType());
			// 从预案规则表中查询出结果
			List<PredictionRuleTable> predictionRules = predictionRuleTableLogic.selectPredictions(predictionRuleTable);
			if (JudgeNullUtil.iList(predictionRules)) {
				List<Equipments> fbEquipments = new ArrayList<>(); // 1,情报板和信号灯设备
				List<Equipments> hdEquipments = new ArrayList<>(); // 2,横洞卷帘门设备
				List<Equipments> cdEquipments = new ArrayList<>(); // 3,车道指示器设备
				List<Equipments> lightEquipments = new ArrayList<>(); // 4,照明设备
				List<Equipments> fjEquipments = new ArrayList<>(); // 5,隧道内风机,广播设备

				for (PredictionRuleTable predictionRule : predictionRules) {
					String categoryCode = predictionRule.getCategoryCode();
					if (categoryCode.startsWith(JBZM) || categoryCode.startsWith(JQZM) || categoryCode.startsWith(YJZM)
							|| categoryCode.startsWith(FXKBQ)) {
						List<Equipments> equipments = getEquipmentsByPredictionRule(predictionRule);
						//生成预案名称
						predictionName = predictionRule.getPredictionName();
						for (Equipments equipment : equipments) {
							lightEquipments.add(equipment);
						}
					} else if (categoryCode.startsWith(HDJIM)) {
						List<Equipments> equipments = getEquipmentsByPredictionRule(predictionRule);
						for (Equipments equipment : equipments) {
							hdEquipments.add(equipment);
						}
					} else if (categoryCode.startsWith(SDFJ)) {
						List<Equipments> equipments = getEquipmentsByPredictionRule(predictionRule);
						for (Equipments equipment : equipments) {
							fjEquipments.add(equipment);
						}
					} else if (categoryCode.startsWith(CDZSQ)) {
						List<Equipments> equipments = getEquipmentsByPredictionRule(predictionRule);
						for (Equipments equipment : equipments) {
							cdEquipments.add(equipment);
						}
					} else if (categoryCode.startsWith(JTXHD)) {
						List<Equipments> equipments = getEquipmentsByPredictionRule(predictionRule);
						for (Equipments equipment : equipments) {
							fbEquipments.add(equipment);
						}
//					} else if (categoryCode.startsWith(prefix)) { // 洞内可变情报板,西簧没有暂时不写
//						List<Equipments> equipments = getEquipmentsByPredictionRule(predictionRule);
//						for (Equipments equipment : equipments) {
//							fbEquipments.add(equipment);
//						}
					} 
				}
				equipmentList1.put(TITTLE, "关闭事故隧道,发布信息");
				equipmentList1.put(EQUIPMENTS, fbEquipments);
				equipmentList2.put(TITTLE, "控制横洞卷帘门");
				equipmentList2.put(EQUIPMENTS, hdEquipments);
				equipmentList3.put(TITTLE, "交通管制");
				equipmentList3.put(EQUIPMENTS, cdEquipments);
				equipmentList4.put(TITTLE, "开启照明设备");
				equipmentList4.put(EQUIPMENTS, lightEquipments);
				equipmentList5.put(TITTLE, "控制风机设备");
				equipmentList5.put(EQUIPMENTS, fjEquipments);
				List<Map<String, Object>> predictionEquipments = new ArrayList<>();
				predictionEquipments.add(equipmentList1);
				predictionEquipments.add(equipmentList2);
				predictionEquipments.add(equipmentList3);
				predictionEquipments.add(equipmentList4);
				predictionEquipments.add(equipmentList5);
				
				prediction.put(PREDICTIONNAME, predictionName);
				prediction.put(PREDICTIONEQUIPMENTS, predictionEquipments);
			}
			ObjectMapper mapper = new ObjectMapper();
			mapper.setSerializationInclusion(Include.NON_NULL);
			sendPredictionAlarmWebSocket(mapper.writeValueAsString(prediction));
		}*/
	}

	@OnError
	public void onError(Throwable throwable, Session session) {
		LOG.error("预案警告推送异常:" + random);
	}

	@OnClose
	public void onClose(Session session) throws IOException {
		webSocketMap.remove(random);
		subOnlineCount(); // 在线数减1
		session.close();
		LOG.debug("预案警告推送连接关闭:" + random);
	}

	public synchronized void sendMessage(String message) throws IOException {
		if (this.session.isOpen()) {
			this.session.getBasicRemote().sendText(message);
		}
	}

	public static synchronized int getOnlineCount() {
		return onlineCount;
	}

	public static synchronized void addOnlineCount() {
		PredictionAlarmWebsocket.onlineCount++;
	}

	public static synchronized void subOnlineCount() {
		PredictionAlarmWebsocket.onlineCount--;
	}
	
	public int sendPredictionAlarmWebSocket(String content) {
		// 遍历所有连接客户工单WebSocket 推送对话
		Iterator<Map.Entry<String, PredictionAlarmWebsocket>> firePlanAlarmWebsocket = PredictionAlarmWebsocket.webSocketMap
				.entrySet().iterator();
		while (firePlanAlarmWebsocket.hasNext()) {
			Map.Entry<String, PredictionAlarmWebsocket> firePlanAlarm = firePlanAlarmWebsocket.next();
			try {
				firePlanAlarm.getValue().sendMessage(content);
			} catch (IOException e) {
			}
		}
		return 0;
	}
	
	/**
	 * 根据设备分类和section查询设备
	 * @param predictionRule
	 * @return
	 */
	/*public List<Equipments> getEquipmentsByPredictionRule(PredictionRuleTable predictionRule){
		String categoryCode = predictionRule.getCategoryCode();
		List<Equipments> equipmentList = new ArrayList<>();
		if (categoryCode != null && (categoryCode.startsWith(JBZM) || categoryCode.startsWith(JQZM) || categoryCode.startsWith(YJZM))
				|| categoryCode.startsWith(JTXHD)) {
			String config = predictionRule.getConfig();
			
			Equipments equipment = new Equipments();
			equipment.setSectionCode(predictionRule.getSectionCode());
			equipment.setCategoryCode(predictionRule.getCategoryCode());
			equipment.setAreaId(predictionRule.getAreaId());
			equipmentList = equipmentsLogic.selectEquipsBySectionAndCategory(equipment);
			if (equipmentList != null) {
				for (Equipments equipControl : equipmentList) {
					List<ControlSolutionConfig.Config> configs = new ArrayList<>();
					if (CommonUtils.isNotEmpty(config)) {
						configs.addAll(JSON.parseArray(config, ControlSolutionConfig.Config.class));
					}
					equipControl.setConfig(configs);
					equipControl.setCommand(config);
				}
			}else {
				LOG.warn(categoryCode + "设备结果为空!");
			}
		} else if (categoryCode.startsWith(FXKBQ)) {
			String solutionCode = predictionRule.getConfig();
			//调用查询情报板的方法
			ControlSolution controlSolution = new ControlSolution();
			controlSolution.setCode(solutionCode);
			Map<String, Object> boardSolution = controlSolutionLogic.selectBoardSolution(controlSolution);
			Equipments equipment = new Equipments();
			equipment.setSectionCode(predictionRule.getSectionCode());
			equipment.setCategoryCode(predictionRule.getCategoryCode());
			equipment.setAreaId(predictionRule.getAreaId());
			equipmentList = equipmentsLogic.selectEquipsBySectionAndCategory(equipment);
			if (JudgeNullUtil.iList(equipmentList)) {
				for (Equipments equipControl : equipmentList) {
					equipControl.setBoardConfig(boardSolution);
					equipControl.setSolutionCode(solutionCode);
				}
			}
		} else if (categoryCode.contains(CDZSQ)) {
			String config = predictionRule.getConfig();
			String lane = predictionRule.getLane(); //车道指示器所在的车道
			
			Equipments equipment = new Equipments();
			equipment.setSectionCode(predictionRule.getSectionCode());
			equipment.setCategoryCode(predictionRule.getCategoryCode());
			equipment.setAreaId(predictionRule.getAreaId());
			if (JudgeNullUtil.iStr(lane) && JudgeNullUtil.iList(equipmentList)) {
				equipment.setLane(lane); 
			}
			//在已知的车道下查询事故区域的设备
			equipmentList = equipmentsLogic.selectEquipsBySectionAndCategoryAndLaneAndAreaId(equipment);
			if (equipmentList != null) {
				for (Equipments equipControl : equipmentList) {
					List<ControlSolutionConfig.Config> configs = new ArrayList<>();
					if (CommonUtils.isNotEmpty(config)) {
						configs.addAll(JSON.parseArray(config, ControlSolutionConfig.Config.class));
					}
					equipControl.setAreaId(predictionRule.getAreaId());
					equipControl.setConfig(configs);
					equipControl.setCommand(config);
					if (JudgeNullUtil.iStr(lane)) {
						equipControl.setLane(lane);
					}
				}
			} else {
				LOG.warn(categoryCode + "设备结果为空!");
			}
		}else if (categoryCode != null) {
			String config = predictionRule.getConfig();
			
			Equipments equipment = new Equipments();
			equipment.setSectionCode(predictionRule.getSectionCode());
			equipment.setCategoryCode(predictionRule.getCategoryCode());
			equipment.setAreaId(predictionRule.getAreaId());
			equipmentList = equipmentsLogic.selectEquipsBySectionAndCategory(equipment);
			if (equipmentList != null) {
				for (Equipments equipControl : equipmentList) {
					List<ControlSolutionConfig.Config> configs = new ArrayList<>();
					if (CommonUtils.isNotEmpty(config)) {
						configs.addAll(JSON.parseArray(config, ControlSolutionConfig.Config.class));
					}
					equipControl.setConfig(configs);
					equipControl.setCommand(config);
				}
			} else {
				LOG.warn(categoryCode + "设备结果为空!");
			}
		}else {
			LOG.warn("预案规则表添加有误,返回的结果中没有设备分类!");
		}
		
		return equipmentList;
	}
	*/
}
